#ifndef __DATABASE_H
#define __DATABASE_H

namespace Db
{
    class DbString : public QString
    {
    public:
        DbString( const QString & text = QString() );
        virtual ~DbString();
        DbString & operator=( const DbString & dbString );

        template< typename T1, typename T2 > DbString argNvlValue( const T1 & value, const T2 & nullValue )
        {
            if (value == nullValue)
                return arg( "NULL" );
    
            return argValue( value );
        }

        DbString argValue( const int & value );
        DbString argValue( const double & value );
        DbString argValue( const QDate & value );
        DbString argValue( const QDateTime & value );
        DbString argValue( const QString & value );
        DbString argValue( const DbString & value );

    private:
        QString escapeString( const QString & text );
        static QMap<QChar, QString> m_patternMap;
    };

    class DbValue
    {
    public:
        DbValue( bool isNull = true, const QByteArray & value = QByteArray() )
        :   m_isNull( isNull ),
            m_value( value )
        {
        }

        void setValue( bool isNull, const QByteArray & value )
        {
            m_isNull = isNull;
            m_value = value;
        }

        bool isNull() const
        {
            return m_isNull;
        }

        const QByteArray & value() const
        {
            return m_value;
        }

    private:
        bool m_isNull;
        QByteArray m_value;
    };

    typedef QVector< DbValue > DbValueVector;
    typedef QVector< DbValueVector > DbResultVector;

    class DbReader
    {
    public:
        DbReader();
        ~DbReader();
        void reset();
        DbResultVector & dbResultVector();
        int recordCount();
        bool read();

        bool isNull( int column );
        int getInt( int column );
        double getDouble( int column );
        QString getString( int column );
        QDate getDate( int column );
        QDateTime getDateTime( int column );

        int getNvlInt( int column, int defaultValue );
        double getNvlDouble( int column, double defaultValue );
        QString getNvlString( int column, const QString & defaultValue = QString() );
        QDate getNvlDate( int column, const QDate & defaultValue );
        QDateTime getNvlDateTime( int column, const QDateTime & defaultValue );

    private:
        int _getInt( const QByteArray & value ) const;
        double _getDouble( const QByteArray & value ) const;
        QString _getString( const QByteArray & value ) const;
        QDate _getDate( const QByteArray & value ) const;
        QDateTime _getDateTime( const QByteArray & value ) const;

    private:
        DbResultVector m_dbResultVector;
        int m_currentRow;
    };

    bool select( const QString & sqlQuery, DbReader & dbReader );
    bool execute( const QString & sqlQuery );
};

#endif
